You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

101 lines
3.0 KiB

<script setup lang="ts">
import { unwrapApiBody, type ApiResponse } from '../../../../utils/http/factory'
import { renderSafeMarkdown } from '../../../../utils/render-markdown'
import { formatOccurredOnDisplay, occurredOnToIsoAttr } from '../../../../utils/timeline-datetime'
const route = useRoute()
const requestFetch = useRequestFetch()
const id = computed(() => route.params.id as string)
type Post = {
id: number
title: string
slug: string
excerpt: string
bodyMarkdown: string
coverUrl: string | null
publishedAt: Date | null
visibility: 'private' | 'unlisted' | 'public'
shareToken?: string | null
}
const { data, pending, error } = await useAsyncData(
() => `me-post-preview-${id.value}`,
async () => {
const res = await requestFetch<ApiResponse<{ post: Post }>>(`/api/me/posts/${encodeURIComponent(id.value)}`)
return unwrapApiBody(res).post
},
{ watch: [id] },
)
const renderedBody = computed(() =>
data.value ? renderSafeMarkdown(data.value.bodyMarkdown) : '',
)
const publishedAtLabel = computed(() =>
data.value?.publishedAt != null ? formatOccurredOnDisplay(data.value.publishedAt) : '',
)
const publishedAtIso = computed(() =>
data.value?.publishedAt != null ? occurredOnToIsoAttr(data.value.publishedAt) : '',
)
const visibilityLabel = computed(() => {
if (!data.value) {
return ''
}
if (data.value.visibility === 'private') {
return '私密预览'
}
if (data.value.visibility === 'unlisted') {
return '仅链接预览'
}
return '公开预览'
})
usePageTitle(() => {
const t = data.value?.title?.trim()
return t ? [t, '预览'] : ['文章预览']
})
</script>
<template>
<UContainer class="py-10 space-y-6">
<div v-if="pending && !data" class="text-muted">
加载中…
</div>
<UAlert v-else-if="error && !data" color="error" title="文章不存在或无权限查看" />
<template v-else-if="data">
<div class="flex flex-wrap items-center gap-2">
<UBadge color="neutral" variant="soft">
{{ visibilityLabel }}
</UBadge>
<UButton :to="`/me/posts/${data.id}`" color="neutral" variant="soft" size="sm">
编辑
</UButton>
</div>
<div v-if="data.coverUrl" class="flex justify-center">
<img
:src="data.coverUrl"
alt=""
class="max-h-64 w-full max-w-2xl rounded-lg object-cover border border-default"
>
</div>
<p v-if="publishedAtLabel" class="text-sm tabular-nums text-muted">
发布于
<time :datetime="publishedAtIso" class="text-default">{{ publishedAtLabel }}</time>
</p>
<h1 class="text-2xl font-semibold">
{{ data.title }}
</h1>
<p v-if="data.excerpt" class="text-muted">
{{ data.excerpt }}
</p>
<article
class="prose prose-neutral dark:prose-invert max-w-none prose-a:text-primary prose-img:rounded-lg prose-headings:text-highlighted prose-p:text-default prose-strong:text-highlighted markdown-body green"
v-html="renderedBody"
/>
</template>
</UContainer>
</template>